﻿#pragma once
#include "XyNet/Common/Iterator.h"
#include <boost/filesystem.hpp>

namespace XyNet
{
	namespace FileSystem
	{
		/// 文件路径
		class XYNET_API Path : public boost::addable<Path>, public boost::dividable<Path>
		{
		public:
			/// 初始化为空路径
			Path();
			/// 初始化为指定路径，假定为UTF8
			Path(const char* diskPath);
			/// 初始化为指定路径，假定为UTF8
			Path(const string& diskPath);
			/// 初始化为指定路径
			Path(const boost::filesystem::path& diskPath);

			/// 连接两个路径，和字符串的+=相同，如abc + def = abcdef
			Path& operator+=(const Path& path);
			/// 用分隔符连接两个路径，如abc / def = abc/def
			Path& operator/=(const Path& path);

			/// 判断路径相等
			bool operator==(const Path& path) const;
			/// 判断路径小于
			bool operator<(const Path& path) const;

			/// 转utf8字符串
			string toUtf8() const;
			/// 转本地多字节字符串
			string toLocal() const;

			/// 是否为空路径""
			bool isEmpty() const;
			/// 清除路径
			void clear();

			/// 获取boost::filesystem::path
			const boost::filesystem::path& getBoostPath() const;

			/// 移除文件名
			Path& removeFilename();
			/// 替换扩展名，如传入".txt"
			Path& replaceExtension(const Path& newExtension = Path());

			/// 获取根路径，返回"c:/"或"/"
			Path getRootPath() const;
			/// 获取根名称，返回"c:"或""
			Path getRootName() const;
			/// 获取根目录，返回"/"或"/"
			Path getRootDirectory() const;
			/// 获取相对路径，如c:/abc/abc，返回abc/abc
			Path getRelativePath() const;
			/// 获取父路径
			Path getParentPath(int level = 1) const;
			/// 获取子路径，如abc/def，得到def
			Path getChildPath(int level = 1) const;
			/// 获取文件名
			Path getFilename() const;          // returns 0 or 1 element path
			/// 获取茎，获取去除扩展名的文件名，如传入"c:/abc.txt"获得"abc"
			Path getStem() const;              // returns 0 or 1 element path
			/// 获取扩展名，如".txt"
			Path getExtension() const;         // returns 0 or 1 element path

			/// 是否有根路径
			bool hasRootPath() const;
			/// 是否有根名称
			bool hasRootName() const;
			/// 是否有根目录
			bool hasRootDirectory() const;
			/// 是否有相对路径
			bool hasRelativePath() const;
			/// 是否有父路径
			bool hasParentPath() const;
			/// 是否有文件名
			bool hasFilename() const;
			/// 是否有茎
			bool hasStem() const;
			/// 是否有扩展名
			bool hasExtension() const;

			/// 是否是绝对路径
			bool isAbsolute() const;
			/// 是否是相对路径
			bool isRelative() const;

			/// 获取路径迭代器
			ConstIterator<Path> getIterator() const;
			/// 获取目录迭代器
			ConstIterator<Path> getDirectoryIterator() const;
			/// 获取递归目录迭代器
			ConstIterator<Path> getRecursiveDirectoryIterator(int maxLevel = -1) const;

		private:
			boost::filesystem::path _boostPath;

		private:
			/// 路径迭代器实现
			class XYNET_API PathIteratorImpl
				: public RangeIteratorImpl<boost::filesystem::path, Path>
			{
			public:
				PathIteratorImpl(const Path* path);
				virtual ~PathIteratorImpl();

			protected:
				virtual shared_ptr<IteratorImpl<Path>> clone() const override;
				virtual Path getCurrent() const override;
			};

			/// 目录迭代器实现
			class XYNET_API DirectoryIteratorImpl : public IteratorImpl<Path>
			{
				typedef boost::filesystem::directory_iterator IteratorType;

			public:
				DirectoryIteratorImpl(const Path* path);
				virtual ~DirectoryIteratorImpl();

				virtual shared_ptr<IteratorImpl<Path>> clone() const override;
				virtual bool moveNext() const override;
				virtual Path getCurrent() const override;

			private:
				const Path* _path;
				mutable IteratorType _current;
				mutable bool _hasNext;
			};

			/// 递归目录迭代器实现
			class XYNET_API RecursiveDirectoryIterator : public IteratorImpl<Path>
			{
				typedef boost::filesystem::recursive_directory_iterator IteratorType;

			public:
				RecursiveDirectoryIterator(const Path* path, int maxLevel = -1);
				virtual ~RecursiveDirectoryIterator();

				virtual shared_ptr<IteratorImpl<Path>> clone() const override;
				virtual bool moveNext() const override;
				virtual Path getCurrent() const override;

			private:
				const Path* _path;
				const int _maxLevel;
				mutable IteratorType _current;
				mutable bool _hasNext;
			};
		};

		/// 是否是可移植路径
		XYNET_API bool isPortable(const Path& path);
		/// 是否存在
		XYNET_API bool isExists(const Path& path);
		/// 是否是文件
		XYNET_API bool isFile(const Path& path);
		/// 是否是目录
		XYNET_API bool isDirectory(const Path& path);

		/// 获取文件大小
		XYNET_API int64 getFileSize(const Path& path);
		/// 获取上次写入时间（安卓不允许修改写入时间，所以只能获取写入时间）
		XYNET_API time_t getLastWriteTime(const Path& path);

		/// 获取初始路径
		XYNET_API Path getInitialPath();
		/// 获取当前路径
		XYNET_API Path getCurrentPath();
		/// 设置当前路径
		XYNET_API void setCurrentPath(const Path& path);

		/// 获取绝对路径（用当前路径合并）
		XYNET_API Path absolute(const Path& path);
		/// 获取规范绝对路径（用当前路径合并，并消除../）
		XYNET_API Path canonical(const Path& path);

		/// 创建目录
		XYNET_API void createDirectories(const Path& path);
		/// 重命名
		XYNET_API void rename(const Path& oldPath, const Path& newPath);
		/// 复制路径
		XYNET_API void copy(const Path& fromPath, const Path& toPath);
		/// 移除
		XYNET_API void remove(const Path& path);

		/// 重载
		XYNET_API bool operator<(const Path& path1, const Path& path2);

		//////////////////////////////////////////////////////////////////////////

		/// 文件
		class XYNET_API File : noncopyable
		{
		public:
			/// 读所有字节
			static Bytes readAllBytes(const Path& path);
			/// 写所有字节
			static void writeAllBytes(const Path& path, const Bytes& bytes);

			/// 附加文本
			static void appendText(const Path& path, const string& text);
		};
	}
}